package zdream.pmfield.test.data.foe;

import org.junit.Before;
import org.junit.Test;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import zdream.pmfield.data.foe.Ability;
import zdream.pmfield.storage.AbilitiesJsonLoader;
import zdream.pmfield.storage.FoeTemplateStorage;
import zdream.pmfield.storage.JsonLoader;
import zdream.pmfield.test.data.foe.MoveCase.Pair;
import zdream.pmfield.test.utils.ResourceConstant;

import static org.junit.Assert.*;
import static zdream.pmfield.storage.FoeTemplateStorage.RES_PATH_ABILITIES_JSON;
import static zdream.pmfield.storage.FoeTemplateStorage.RES_PATH_STAGE_ABILITIES_JSON;

/**
 * @author Zdream
 * @date 2023-12-18
 * @since 0.0.1
 */
public class AbilityCase {
	FoeTemplateStorage storage;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.loadAbilities();
		storage.loadAbilitiesInResource(ResourceConstant.RES_PATH_TEST_ABILITIES_JSON);
	}

	@Test
	public void testCheckAbilitiesJson() {
		Arrays.asList(
				RES_PATH_ABILITIES_JSON,
				RES_PATH_STAGE_ABILITIES_JSON,
				ResourceConstant.RES_PATH_TEST_ABILITIES_JSON
		).forEach(this::testCheckAbilitiesJsonForPath);
	}

	private void testCheckAbilitiesJsonForPath(String resourcePath) {
		ClassLoader loader = getClass().getClassLoader();
		InputStream inputStream = loader.getResourceAsStream(resourcePath);
		final JsonElement element = JsonLoader.fromInputStream(inputStream);
		assertTrue(element.isJsonArray());

		JsonArray array = element.getAsJsonArray();
		Set<Pair> idSet = new HashSet<>();
		Map<Integer, String> idNameMap = new HashMap<>();

		for (JsonElement jsonItem : array) {
			assertTrue(jsonItem.isJsonObject());

			JsonObject object = jsonItem.getAsJsonObject();
			assertTrue(object.has("id"));

			JsonElement idElement = object.get("id");
			assertTrue(idElement.isJsonPrimitive());
			JsonPrimitive idPrimitive = idElement.getAsJsonPrimitive();
			assertTrue(idPrimitive.isNumber());

			int id = idPrimitive.getAsInt();
			assertTrue(id > 0);
			System.out.println("现在正在检查 " + resourcePath + " 中的元素: id=" + id);

			final Ability ability = AbilitiesJsonLoader.loadOne(object);
			assertNotNull(ability);
			assertEquals(id, ability.id);

			Pair pair = new Pair(id, ability.level);
			assertFalse(idSet.contains(pair));
			idSet.add(pair);

			// check name
			// 每个 id 相同的 move 名称必须一样
			assertNotNull(ability.name);
			assertTrue(ability.name.length() > 0);
			if (idNameMap.containsKey(ability.id)) {
				assertEquals(idNameMap.get(ability.id), ability.name);
			} else {
				idNameMap.put(ability.id, ability.name);
			}

			// check level
			assertTrue(ability.level > 0);
			assertTrue(ability.level < 10);

			// check addition
			if (object.has("a")) {
				assertNotNull(ability.additions);
				assertTrue(ability.additions.length > 0);

				final JsonElement additionalElement = object.get("a");
				if (additionalElement.isJsonArray()) {
					final JsonArray additionalArray = additionalElement.getAsJsonArray();
					assertEquals(additionalArray.size(), ability.additions.length);
				} else {
					assertTrue(additionalElement.isJsonPrimitive());
					assertTrue(additionalElement.getAsJsonPrimitive().isString());
					assertEquals(1, ability.additions.length);
				}

				assertTrue(Arrays.stream(ability.additions).allMatch(text -> text.length() > 0));
			} else {
				assertNull(ability.additions);
			}
		}
	}
}
